/**
 * Copyright (C) 2010-2016 eBusiness Information, Excilys Group
 * Copyright (C) 2016-2020 the AndroidAnnotations project
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed To in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.ohosannotations.internal;

import com.helger.jcodemodel.AbstractJClass;
import com.helger.jcodemodel.JCodeModel;
import com.helger.jcodemodel.JDefinedClass;

import org.ohosannotations.OhosAnnotationsEnvironment;
import org.ohosannotations.Option;
import org.ohosannotations.handler.AnnotationHandler;
import org.ohosannotations.handler.GeneratingAnnotationHandler;
import org.ohosannotations.helper.OhosManifest;
import org.ohosannotations.holder.GeneratedClassHolder;
import org.ohosannotations.internal.model.AnnotationElements;
import org.ohosannotations.internal.process.ProcessHolder;
import org.ohosannotations.plugin.OhosAnnotationsPlugin;
import org.ohosannotations.rclass.IRClass;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;

/**
 * 内部注释环境
 *
 * @author dev
 * @since 2021-07-22
 */
public class InternalOhosAnnotationsEnvironment implements OhosAnnotationsEnvironment {
    private final ProcessingEnvironment processingEnvironment;
    private final Options options;
    private final AnnotationHandlers annotationHandlers;

    private List<OhosAnnotationsPlugin> plugins;

    private IRClass rClass;
    private OhosManifest ohosManifest;

    private AnnotationElements extractedElements;

    private AnnotationElements validatedElements;

    private ProcessHolder processHolder;

    /**
     * 内部注释环境
     *
     * @param processingEnvironment 处理环境中
     */
    InternalOhosAnnotationsEnvironment(ProcessingEnvironment processingEnvironment) {
        this.processingEnvironment = processingEnvironment;
        options = new Options(processingEnvironment);
        annotationHandlers = new AnnotationHandlers();
    }

    /**
     * 设置插件
     *
     * @param plugins 插件
     */
    public void setPlugins(List<OhosAnnotationsPlugin> plugins) {
        this.plugins = plugins;
        for (OhosAnnotationsPlugin plugin : plugins) {
            options.addAllSupportedOptions(plugin.getSupportedOptions());
            for (AnnotationHandler<?> annotationHandler : plugin.getHandlers(this)) {
                annotationHandlers.add(annotationHandler);
            }
        }
    }

    /**
     * setOhosEnvironment
     *
     * @param rClass r类
     * @param ohosManifest 清单
     */
    public void setOhosEnvironment(IRClass rClass, OhosManifest ohosManifest) {
        this.rClass = rClass;
        this.ohosManifest = ohosManifest;
    }

    /**
     * setExtractedElements
     *
     * @param extractedElements 提取的元素
     */
    public void setExtractedElements(AnnotationElements extractedElements) {
        this.extractedElements = extractedElements;
    }

    /**
     * setValidatedElements
     *
     * @param validatedElements 验证元素
     */
    public void setValidatedElements(AnnotationElements validatedElements) {
        this.validatedElements = validatedElements;
    }

    /**
     * setProcessHolder
     *
     * @param processHolder 过程持有人
     */
    public void setProcessHolder(ProcessHolder processHolder) {
        this.processHolder = processHolder;
    }

    /**
     * ProcessingEnvironment
     *
     * @return processingEnvironment
     */
    @Override
    public ProcessingEnvironment getProcessingEnvironment() {
        return processingEnvironment;
    }

    /**
     * getSupportedOptions
     *
     * @return options
     */
    @Override
    public Set<String> getSupportedOptions() {
        return options.getSupportedOptions();
    }

    /**
     * getOptionValue
     *
     * @param option 选项
     * @return options
     */
    @Override
    public String getOptionValue(Option option) {
        return options.get(option);
    }

    /**
     * getOptionValue
     *
     * @param optionKey 选择键
     * @return options
     */
    @Override
    public String getOptionValue(String optionKey) {
        return options.get(optionKey);
    }

    /**
     * getOptionBooleanValue
     *
     * @param option 选项
     * @return options
     */
    @Override
    public boolean getOptionBooleanValue(Option option) {
        return options.getBoolean(option);
    }

    /**
     * getOptionBooleanValue
     *
     * @param optionKey 选择键
     * @return options
     */
    @Override
    public boolean getOptionBooleanValue(String optionKey) {
        return options.getBoolean(optionKey);
    }

    /**
     * getSupportedAnnotationTypes
     *
     * @return annotationHandlers
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return annotationHandlers.getSupportedAnnotationTypes();
    }

    /**
     * getHandlers
     *
     * @return annotationHandlers
     */
    @Override
    public List<AnnotationHandler<?>> getHandlers() {
        return annotationHandlers.get();
    }

    /**
     * getDecoratingHandlers
     *
     * @return annotationHandlers
     */
    @Override
    public List<AnnotationHandler<?>> getDecoratingHandlers() {
        return annotationHandlers.getDecorating();
    }

    /**
     * getGeneratingHandlers
     *
     * @return annotationHandlers
     */
    @Override
    public List<GeneratingAnnotationHandler<?>> getGeneratingHandlers() {
        return annotationHandlers.getGenerating();
    }

    /**
     * getRClass
     *
     * @return rClass
     */
    @Override
    public IRClass getRClass() {
        return rClass;
    }

    /**
     * getOhosManifest
     *
     * @return ohosManifest
     */
    @Override
    public OhosManifest getOhosManifest() {
        return ohosManifest;
    }

    /**
     * getExtractedElements
     *
     * @return extractedElements
     */
    @Override
    public AnnotationElements getExtractedElements() {
        return extractedElements;
    }

    /**
     * getValidatedElements
     *
     * @return validatedElements
     */
    @Override
    public AnnotationElements getValidatedElements() {
        return validatedElements;
    }

    /**
     * getCodeModel
     *
     * @return processHolder
     */
    @Override
    public JCodeModel getCodeModel() {
        return processHolder.codeModel();
    }

    /**
     * getJClass
     *
     * @param fullyQualifiedName 全限定名
     * @return processHolder
     */
    @Override
    public AbstractJClass getJClass(String fullyQualifiedName) {
        return processHolder.refClass(fullyQualifiedName);
    }

    /**
     * getJClass
     *
     * @param clazz clazz
     * @return processHolder
     */
    @Override
    public AbstractJClass getJClass(Class<?> clazz) {
        return processHolder.refClass(clazz);
    }

    /**
     * getDefinedClass
     *
     * @param fullyQualifiedName 全限定名
     * @return processHolder
     */
    @Override
    public JDefinedClass getDefinedClass(String fullyQualifiedName) {
        return processHolder.definedClass(fullyQualifiedName);
    }

    /**
     * getGeneratedClassHolder
     *
     * @param element 元素
     * @return processHolder
     */
    @Override
    public GeneratedClassHolder getGeneratedClassHolder(Element element) {
        return processHolder.getGeneratedClassHolder(element);
    }

    /**
     * getClasses
     *
     * @return processHolder
     */
    @Override
    public ProcessHolder.Classes getClasses() {
        return processHolder.classes();
    }

    /**
     * getGeneratingAnnotations
     *
     * @return annotationHandlers
     */
    @Override
    public List<Class<? extends Annotation>> getGeneratingAnnotations() {
        return annotationHandlers.getGeneratingAnnotations();
    }

    /**
     * isOhosAnnotation
     *
     * @param annotationQualifiedName 注释限定名称
     * @return getSupportedAnnotationTypes
     */
    @Override
    public boolean isOhosAnnotation(String annotationQualifiedName) {
        return getSupportedAnnotationTypes().contains(annotationQualifiedName);
    }

    /**
     * getPlugins
     *
     * @return plugins
     */
    @Override
    public List<OhosAnnotationsPlugin> getPlugins() {
        return plugins;
    }
}
